package com.sunshine.logistic;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;

import org.apache.commons.io.FileUtils;

/**
 * Created by hadoop on 17/12/4.
 */
public class BaseLogistic {

    public static double[][] loadDataSet() throws IOException {
        List<String> lists = FileUtils.readLines(new File("src/main/resources/dataset.txt"), Charset.defaultCharset());
        double[][] dataSet = new double[lists.size()][3];//默认加一个1
        int index = 0;
        for (String line : lists) {
            dataSet[index][0] = 1;
            String[] arr = line.split("\t");
            dataSet[index][1] = Double.parseDouble(arr[0]);
            dataSet[index][2] = Double.parseDouble(arr[1]);
            //dataSet[index][3] =  Double.parseDouble(arr[2]);
            index++;
        }

        return dataSet;
    }

    public static double[] loadLabel() throws IOException {
        List<String> lists = FileUtils.readLines(new File("src/main/resources/dataset.txt"), Charset.defaultCharset());
        double[] dataSet = new double[lists.size()];
        int index = 0;
        for (String line : lists) {
            String[] arr = line.split("\t");
            dataSet[index++] = Double.parseDouble(arr[2]);
        }

        return dataSet;
    }

    public static double[] sigmod(double[] data) {
        double[] result = new double[data.length];
        for (int i = 0; i < data.length; i++) {
            result[i] = sigmod(data[i]);
        }
        return result;
    }

    public static double sigmod(double data) {
        return 1.0 / (1 + Math.pow(Math.E, -data));
    }

    public static double[] gradAscent(double[][] dataMatIn, double[] classLaebls) throws IOException {
        double[][] dataSet = loadDataSet();
        double[] labels = loadLabel();
        int iteratorTimes = 2000;

        double[] weights = init(dataMatIn[0].length, 1.0);

        double alpha = 0.001;

        for (int i = 1; i <= iteratorTimes; i++) {
            double[] result = sigmod(mul(dataSet, weights));
            double[] error = sub(labels, result);
            double[][] transpose = transpose(dataSet);
            double[] mulResult1 = mul(transpose, error);
            double[] mulResult2 = mul(mulResult1, alpha);
            weights = add(weights, mulResult2);
        }

        return weights;

    }

    private static double[] add(double[] weights, double[] mul) {
        double[] data = new double[weights.length];
        int length = weights.length;
        for (int i = 0; i < length; i++) {
            data[i] = weights[i] + mul[i];
        }
        return data;
    }

    private static double[][] transpose(double[][] m) {
        int i = m.length;
        int j = m[0].length;

        double[][] result = new double[j][i];

        for (int k = 0; k < i; k++) {
            for (int z = 0; z < j; z++) {
                result[z][k] = m[k][z];
            }
        }
        return result;
    }

    private static double[] init(int length, double v) {
        double[] result = new double[length];
        for (int i = 0; i < length; i++) {
            result[i] = v;
        }
        return result;
    }

    private static double[] sub(double[] d1, double[] d2) {
        double[] error = new double[d1.length];
        int length = d1.length;
        for (int i = 0; i < length; i++) {
            error[i] = d1[i] - d2[i];
        }
        return error;
    }

    public static double[] mul(double[][] data1, double[] data2) {
        int rows = data1.length;
        int cols = data1[0].length;
        double[] result = new double[data1.length];

        for (int i = 0; i < rows; i++) {
            double sum = 0.0;
            for (int j = 0; j < cols; j++) {
                sum += data1[i][j] * data2[j];
            }

            result[i] = sum;
        }
        return result;
    }

    public static double[] mul(double[] data, double v) {
        int rows = data.length;
        double[] result = new double[data.length];

        for (int i = 0; i < rows; i++) {
            result[i] = v * data[i];
        }
        return result;
    }

    public static double prediction(double[] data) throws IOException {
        double[] v = gradAscent(loadDataSet(), loadLabel());
        return sigmod(v[0] + data[0] * v[1] + data[1] * v[2]);
    }

    public static void main(String[] args) throws IOException {

        // double [] v  = gradAscent(loadDataSet(),loadLabel());

        System.out.println(prediction(new double[] {-2.168791,0.143632}));

    }

}
